package com.oujiong.iplimiter.aop.limit;


import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.Objects;

@Component
public class InterceptorMzLimit extends HandlerInterceptorAdapter {

    final static Logger logger= LoggerFactory.getLogger(InterceptorMzLimit.class);


    @Autowired
    CallLuaService callLuaService;


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //判断请求是否属于方法的请求
        if ( !(handler instanceof HandlerMethod) ) {
            return  true;
        }
        HandlerMethod hm = (HandlerMethod) handler;
        //获取方法中的注解,看是否有该注解
        MzLimit mzLimit = hm.getMethodAnnotation(MzLimit.class);
        if(mzLimit == null)  return true;  //如果没有 ，则不管，直接返回去执行业务
        Integer seconds = mzLimit.second(), maxCount = mzLimit.maxCount(),count=null;
        String[] typeArr=mzLimit.typeArr();
        String remoteHost = request.getRemoteAddr();
        String localHost = InetAddress.getLocalHost().getHostAddress();
        String callResource =hm.getMethod().getDeclaringClass().getName()+"."+hm.getMethod().getName();
        String key=null;
        for(String type:typeArr){
            if(Objects.equals(type,MzLimit.IP)){ /*如果是根据IP进行限流*/
                key=remoteHost+":"+localHost+":"+callResource;
            }else { /*根据访问接口 进行限流*/
                key=localHost+":"+callResource;
            }
            Object tmpCount = callLuaService.call(luastr.toString(),Arrays.asList(key),Arrays.asList(String.valueOf(seconds) )  );
            count=Integer.parseInt(tmpCount.toString());
            if(count>=maxCount){
                logger.warn("限流：超过了最大访问次数：TYPE:{}, key:{},seconds:{},maxCount:{}",type,key,seconds,maxCount);
//                throw new BusinessException(1001,"超过了最大访问次数");
//                CommonResult<String> result = CommonResult.failure("1001","超过了最大访问次数");
                render(response,null);
                return false;
            }
        }
        return  true;
    }

    private void render(HttpServletResponse response, String result)throws Exception {
        response.setContentType("application/json;charset=UTF-8");
        OutputStream out = response.getOutputStream();
        String str  = JSONObject.toJSONString(result);
        out.write(str.getBytes("UTF-8"));
        out.flush();
        out.close();
    }


    StringBuilder luastr=new StringBuilder()
            .append("local key=KEYS[1]").append("\n")
            .append("local seconds=ARGV[1]").append("\n")
            .append("local count=redis.call('incr', key)").append("\n")
            .append("if  count == 1 then").append("\n")
            .append("   redis.call('EXPIRE',key,seconds)").append("\n")
            .append("end").append("\n")
            .append("return tostring(count)").append("\n");

}
